package com.example.example.config;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.example.example.modules.test.dao.entity.DictEntity;
import com.example.example.modules.test.service.DictEntityService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author qiancheng@cqxyy.net
 * @date 2022/9/8
 */
@Aspect
@Slf4j
@Component
public class GetTranslateAspect {

    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    DictEntityService dictEntityService;

    /**
     * 定义切点Pointcut
     */
    @Pointcut("execution(public * com.example.example..*.*Api.*(..))")
    public void excudeService(){}

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
        Object result = pjp.proceed();
        result = this.toDictType(result);
        return result;
    }

    private Object toDictType(Object result) {
        List<JSONObject> items = new ArrayList<>();

        //加了GetTranslate注解的字段
        List<Field> fieldList = new ArrayList<>();

        //key = 注解上的value,数据库中的colum, value = 要取得一些值
        Map<String,List<String>> dataListMap = new HashMap<>();

        //Api那一步马上要返回到前端的结果集
        List<Object> records = new ArrayList<>();
        Object tmp = ((BaseResponse) result).getData();
        if(tmp instanceof List){
            records = (List) tmp;
        }else{
            List<Object> tmp1 = new ArrayList<>();
            tmp1.add(tmp);
            records = tmp1;
        }
        //首先检测结果集中是否含有该注解
        if(!haveAnnotion((records))){
            return result;
        }
        //组装需要查询的信息
        for(Object record : records){
            String json = "";
            //将每一个响应都拆成json
            try {
                json = objectMapper.writeValueAsString(record);
            }catch (JsonProcessingException e){
                log.error("Json解析失败" + e.getMessage(),e);
            }
            //将json变为json对象，顺序不变
            JSONObject item= JSONObject.parseObject(json, Feature.OrderedField);
            for(Field field : getAllFields(record)){
                if(StringUtils.isBlank(item.getString(field.getName()))){
                    continue;
                }
                //将有此注解的属性保存
                if(field.getAnnotation(GetTranslate.class) != null){
                    //重复值不添加
                    if(!fieldList.contains(field)){
                        fieldList.add(field);
                    }
                    //获取注解信息
                    String colum = field.getAnnotation(GetTranslate.class).value();

                    //开始拼装查询需要信息
                    List<String> dataList;
                    String code = colum;
                    dataList = dataListMap.computeIfAbsent(code,key->new ArrayList<>());
                    //多次迭代，将所有搜索的数据筛选后存入dataList中
                    List<String> addList = Arrays.asList(item.getString(field.getName()).replace("[","").replace("]","").split(","));
                    List<String> filterList = addList.stream().filter(s -> !dataList.contains(s)).collect(Collectors.toList());
                    dataList.addAll(filterList);
                }
            }
            items.add(item);
        }
        //通过数据库查询结果
        Map<String,List<DictType>> searchResult = new HashMap<>();
        for (Map.Entry<String,List<String>> entry : dataListMap.entrySet()){
            Example example = new Example(DictEntity.class);
            Example.Criteria criteria= example.createCriteria();
            criteria.andEqualTo("colum",entry.getKey());
            criteria.andIn("code",entry.getValue());
            List<DictEntity> dictEntities = dictEntityService.selectByExample(example);
            List<DictType> dictTypes = new ArrayList<>();
            dictEntities.stream().forEach(s ->{
                DictType dictType = new DictType();
                BeanUtils.copyProperties(s,dictType);
                dictTypes.add(dictType);
            });
            searchResult.put(entry.getKey(),dictTypes);
        }
        System.out.println(searchResult);

        //将结果添加进返回值中
        for(JSONObject record : items){
            Map<String,List<DictType>> map = new HashMap<>();
            for(Field field : fieldList){
                List<DictType> dictTypeResult = new ArrayList<>();
                String value = field.getAnnotation(GetTranslate.class).value();
                List<DictType> dictTypes = searchResult.get(value);
                List<String> codes = Arrays.asList(record.getString(field.getName()).replace("[","").replace("]","").split(","));
                for(String code : codes){
                    for(DictType dictType : dictTypes){
                        if(code.equals(dictType.getCode())){
                            dictTypeResult.add(dictType);
                            break;
                        }
                    }
                }
                map.put(value,dictTypeResult);
            }
            record.put("dictMap",map);
        }
        ((BaseResponse)result).setData(items);
        return result;
    }


    //检测结果集中是否含有该注解
    public Boolean haveAnnotion(List<Object> records) {
        if(records != null && !"".equals(records) && records.size() >0){
            for(Field field : getAllFields(records.get(0))){
                if(field.getAnnotation(GetTranslate.class) != null && !field.getAnnotation(GetTranslate.class).equals("")){
                    return true;
                }
            }
        }
        return false;
    }

    //取出List结果集中的每个属性
    public Field[] getAllFields(Object object){
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
}
